﻿using MyFurion.Application;
using MyFurion.Unility.EnumData;

namespace MyFurion.Start
{
    /// <summary>
    /// sqlsugarIOC注册
    /// </summary>
    public static class SqlSugarSetup
    {
        public static void AddSqlsugarSetup()
        {
            List<IocConfig> iocConfigs = App.GetConfig<List<IocConfig>>("ConnectionConfigs");//获取数据库连接配置
            SugarIocServices.AddSqlSugar(iocConfigs);
            SugarIocServices.ConfigurationSugar(db =>
            {
                foreach (var iocItem in iocConfigs)
                {
                    SqlSugarProvider dbClient = db.GetConnection(iocItem.ConfigId);
                    SetQueryFilter(dbClient);
                    dbClient.Aop.OnLogExecuting = (sql, pars) =>
                    {
                        string sqlstr = SqlProfiler.ParameterFormat(sql, pars);
                        Log.Information(sqlstr);
                        Console.WriteLine(sqlstr);
                        Console.WriteLine();
                    };
                    var dbtype = dbClient.CurrentConnectionConfig.DbType;
                    dbClient.CurrentConnectionConfig.ConfigureExternalServices = new ConfigureExternalServices()
                    {
                        //自定义类型多库兼容
                        EntityService = (c, p) =>
                        {
                            if (p.DataType == CommonConst.DB_STRING_MAX)
                            {
                                if (dbtype == DbType.MySql)
                                {
                                    p.DataType = "longtext";
                                }
                                else if (dbtype == DbType.SqlServer)
                                {
                                    p.DataType = "nvarchar(max)";
                                }
                            }

                        }
                    };
                }
            });
            CreateTable(iocConfigs);
            InitData();
        }
        /// <summary>
        /// 创建数据库表 codefirst
        /// </summary>
        private static void CreateTable(List<IocConfig> iocConfigs)
        {
            foreach (var item in iocConfigs)
            {
                string configId = item.ConfigId;
                ISqlSugarClient db = DbScoped.SugarScope.GetConnectionScope(configId);
                db.DbMaintenance.CreateDatabase();//没有数据库的时候创建数据库
                var tableLists = db.DbMaintenance.GetTableInfoList();
                var files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "MyFurion.Model.dll");
                if (files.Length > 0)
                {
                    Type[] types = Assembly.LoadFrom(files[0]).GetTypes().Where(it => it.BaseType == typeof(BaseEntity)).ToArray();
                    foreach (var entityType in types)
                    {                    
                        var sugarTableAttr = entityType.GetCustomAttribute<SugarTable>();//获取SugarTable特性
                        if (sugarTableAttr != null)
                        {
                            string tableName = sugarTableAttr.TableName;//根据特性获取表名称
                            string tableNameLower = tableName.ToLower();
                            var configid = entityType.GetCustomAttribute<TenantAttribute>()?.configId;//根据特性获取租户id
                            string tenantId = configid == null ? "0" : Convert.ToString(configId);
                            if (!tableLists.Any(p => p.Name == tableName || p.Name == tableNameLower) && configId == tenantId)
                            {
                                //创建数据表包括字段更新
                                db.CodeFirst.InitTables(entityType);
                            }
                        }
                    }
                    db.Close();
                }
            }
        }
        /// <summary>
        /// 添加全局过滤器
        /// </summary>
        /// <param name="provider"></param>
        private static void SetQueryFilter(SqlSugarProvider provider)
        {
            bool isSuperAdmin = CurrentUserInfo.IsSuperAdmin;
            int orgAuth = CurrentUserInfo.OrgPer;
            string orgPerIds = CurrentUserInfo.OrgPerId;
            long userId = CurrentUserInfo.UserId;
            long orgId = CurrentUserInfo.OrgId;
            //无需全局机构数据权限过滤的数据表
            List<string> noOrgAuthTable = new List<string> {
                "ErrorLog","RequestLog","SqlLog","ConfigInfo", "DictDetailInfo", "DictInfo", "MenuInfo", "OrgInfo", "OrgPerInfo","RoleInfo","RoleMenuInfo",
                "SysFile","UserInfo","UserRoleInfo"
            };
            //添加全局过滤器
            var files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "MyFurion.Model.dll");
            if (files.Length > 0)
            {
                Type[] types = Assembly.LoadFrom(files[0]).GetTypes().Where(it => it.BaseType == typeof(BaseEntity)).ToArray();
                foreach (var entityType in types)
                {
                    //string tableName = entityType.GetCustomAttribute<SugarTable>().TableName;//根据特性获取表名称
                    var lambda = DynamicExpressionParser.ParseLambda( new[] { Expression.Parameter(entityType, "it") },typeof(bool), $"{nameof(BaseEntity.IsDeleted)} ==  @0",false);
                    provider.QueryFilter.Add(new TableFilterItem<object>(entityType, lambda, true)); //将Lambda传入过滤器
                    //机构数据权限过滤                    
                    if (!isSuperAdmin&&!noOrgAuthTable.Any(g=>g==entityType.Name))
                    {
                        if (orgAuth != (int)EnumOrgAuthority.All)
                        {
                            if (orgAuth == (int)EnumOrgAuthority.Self)
                            {
                                var lambdaUser = DynamicExpressionParser.ParseLambda(new[] { Expression.Parameter(entityType, "it") }, typeof(bool), $"{nameof(BaseEntity.CreateUserId)} ==  @0", userId.ToString());
                                provider.QueryFilter.Add(new TableFilterItem<object>(entityType, lambdaUser, true)); //将Lambda传入过滤器
                            }
                            else
                            {
                                List<long> orgIds = new();
                                if (orgAuth == (int)EnumOrgAuthority.Org)
                                {
                                    orgIds.Add(CurrentUserInfo.OrgId);
                                }
                                else if (orgAuth == (int)EnumOrgAuthority.OrgChild || orgAuth == (int)EnumOrgAuthority.CustomOrg)
                                {
                                    if (!string.IsNullOrWhiteSpace(orgPerIds))
                                    {
                                        orgIds = Furion.JsonSerialization.JSON.Deserialize<List<long>>(orgPerIds);
                                    }
                                }
                                if (orgIds.Any())
                                {
                                    var strOrgIds = orgIds.Select(g=>g.ToString()).ToList();
                                    var lambdaOrg = DynamicExpressionParser.ParseLambda(new[] { Expression.Parameter(entityType, "it") }, typeof(bool), $"it=>@0.Contains(it.{nameof(BaseEntity.CreateOrgId)})", strOrgIds);
                                    provider.QueryFilter.Add(new TableFilterItem<object>(entityType, lambdaOrg, true)); //将Lambda传入过滤器
                                }
                            }
                        }
                    }
                }
            }
            //插入/更新过滤器,用于审计日志
            provider.Aop.DataExecuting = (oldValue, entityInfo) =>
            {
                if (entityInfo.OperationType == DataFilterType.InsertByObject)
                {
                    if (entityInfo.PropertyName == "CreateUserId")
                    {
                        entityInfo.SetValue(CurrentUserInfo.UserId.ToString());
                    }
                    if (entityInfo.PropertyName == "CreateUser")
                    {
                        entityInfo.SetValue(CurrentUserInfo.UserName);
                    }
                    if (entityInfo.PropertyName == "CreateOrgId")
                    {
                        entityInfo.SetValue(CurrentUserInfo.OrgId.ToString());
                    }
                }
                //update生效        
                if (entityInfo.OperationType == DataFilterType.UpdateByObject)
                {
                    if (entityInfo.PropertyName == "ModifyTime")
                    {
                        entityInfo.SetValue(DateTime.Now);
                    }
                    if (entityInfo.PropertyName == "ModifyUserId")
                    {
                        entityInfo.SetValue(CurrentUserInfo.UserId.ToString());
                    }
                    if (entityInfo.PropertyName == "ModifyUser")
                    {
                        entityInfo.SetValue(CurrentUserInfo.UserName);
                    }
                }
            };
        }
        /// <summary>
        /// 初始化种子数据
        /// </summary>
        private static void InitData()
        {
            var orgRep = App.GetService<OrgRepository>();
            var userRep=App.GetService<UserRepository>();
            var roleRep=App.GetService<RoleRepository>();
            var configRep=App.GetService<ConfigRepository>();

            bool orgEmpty = orgRep.IsEmptyData().Result;
            if (orgEmpty)
            {
                var result=orgRep.Insert(SeedDataInfo.OrgSeedData).Result;
            }
            bool userEmpty = userRep.IsEmptyData().Result;
            if (userEmpty)
            {
                var result = userRep.Insert(SeedDataInfo.UserSeedData).Result;
            }
            bool roleEmpty = roleRep.IsEmptyData().Result;
            if (roleEmpty)
            {
                var result = roleRep.Insert(SeedDataInfo.RoleSeedData).Result;
            }
            bool configEmpty = configRep.IsEmptyData().Result;
            if (configEmpty)
            {
                var result = configRep.Insert(SeedDataInfo.ConfigSeedData).Result;
            }
        }
    }
}